/**
 * @file drv_usart.h
 * @brief 本文件包含了 USART 通信的函数原型，支持 DMA 使用 STM32 HAL 库。
 *
 * 该头文件提供了 USART 初始化函数以及使用 DMA 发送数据的函数，
 * 还包括 DMA 接收完成后调用的回调函数。
 */

#include "string.h"
#include "drv_usart.h"
#include "stdint.h"
#include "usart.h"
#include "sys_manager.h"
#include "app_config.h"
#include "app_sys.h"
#include "drv_sys.h"

extern UART_HandleTypeDef huart1;
extern UART_HandleTypeDef huart2;
extern UART_HandleTypeDef huart3;
extern DMA_HandleTypeDef hdma_usart1_rx;
extern DMA_HandleTypeDef hdma_usart2_rx;
extern DMA_HandleTypeDef hdma_usart3_rx;

extern DMA_HandleTypeDef hdma_usart1_tx;
extern DMA_HandleTypeDef hdma_usart2_tx;
extern DMA_HandleTypeDef hdma_usart3_tx;

volatile uint8_t uart_dma_tx_complete = 1; 

uint8_t uart1_rx_buffer[RX_BUF_SIZE]={0};//接收缓存
uint8_t uart2_rx_buffer[RX_BUF_SIZE]={0};//接收缓存
uint8_t uart3_rx_buffer[RX_BUF_SIZE]={0};//接收缓存

/* 声明UART实例配置 */
static const uart_instance_t uart1_instance = {
    .huart     = &huart1,
    .hdma_rx   = &hdma_usart1_rx,
    .hdma_tx   = &hdma_usart1_tx,
    .rx_buffer = uart1_rx_buffer,
    .src_id    = USART1_PORT
};

static const uart_instance_t uart2_instance = {
    .huart     = &huart2,
    .hdma_rx   = &hdma_usart2_rx,
    .hdma_tx   = &hdma_usart2_tx,
    .rx_buffer = uart2_rx_buffer,
    .src_id    = USART2_PORT
};

static const uart_instance_t uart3_instance = {
    .huart     = &huart3,
    .hdma_rx   = &hdma_usart3_rx,
    .hdma_tx   = &hdma_usart3_tx,
    .rx_buffer = uart3_rx_buffer,
    .src_id    = USART3_PORT
};

void drv_usart_init()
{   
    //开启一次DMA接收中断
    HAL_UARTEx_ReceiveToIdle_DMA(&huart1, uart1_rx_buffer, RX_BUF_SIZE);
    HAL_UARTEx_ReceiveToIdle_DMA(&huart2, uart2_rx_buffer, RX_BUF_SIZE);
    HAL_UARTEx_ReceiveToIdle_DMA(&huart3, uart3_rx_buffer, RX_BUF_SIZE);
    __HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT);
    __HAL_DMA_DISABLE_IT(&hdma_usart2_rx, DMA_IT_HT);
    __HAL_DMA_DISABLE_IT(&hdma_usart3_rx, DMA_IT_HT);
}


// 获取限流比例：返回每N次调用发送1次
static uint8_t get_send_limit_ratio(DRV_USART_PORT port)
{
    uint8_t error_count = 0;
    uint8_t consecutive_failures = 0;
    
    switch(port) {
        case USART1_PORT:
            error_count = system_status.uart.uart1_error_count;
            consecutive_failures = system_status.uart.uart1_consecutive_send_failures;
            break;
        case USART2_PORT:
            error_count = system_status.uart.uart2_error_count;
            consecutive_failures = system_status.uart.uart2_consecutive_send_failures;
            break;
        case USART3_PORT:
            error_count = system_status.uart.uart3_error_count;
            consecutive_failures = system_status.uart.uart3_consecutive_send_failures;
            break;
        default:
            return 1;
    }
    
    // 错误计数 <= 3 时不限流
    if (error_count <= 3) {
        return 1;
    }
    
    // 递进式限流策略
    if (consecutive_failures >= 9) {
        return 8;  // 每8次调用发送1次 (重度限流)
    } else if (consecutive_failures >= 6) {
        return 4;  // 每4次调用发送1次 (中度限流)  
    } else if (consecutive_failures >= 3) {
        return 2;  // 每2次调用发送1次 (轻度限流)
    }
    
    return 1;  // 正常发送
}

void drv_usart_send_data(DRV_USART_PORT port, uint8_t *send_data, uint16_t size)
{
    // 根据串口选择句柄
    UART_HandleTypeDef *huart = NULL;
    
    // 检查数据指针是否为 NULL
    if (send_data == NULL) 
    {
        return; // 不发送数据
    }
    
    // 检查是否需要限流
    uint8_t limit_ratio = get_send_limit_ratio(port);
    if (limit_ratio > 1) {
        uint8_t *delay_counter = NULL;
        switch(port) {
            case USART1_PORT:
                delay_counter = &system_status.uart.uart1_send_delay_counter;
                break;
            case USART2_PORT:
                delay_counter = &system_status.uart.uart2_send_delay_counter;
                break;
            case USART3_PORT:
                delay_counter = &system_status.uart.uart3_send_delay_counter;
                break;
        }
        
        if (delay_counter) {
            (*delay_counter)++;
            if (*delay_counter < limit_ratio) {
                return; // 跳过本次发送
            }
            *delay_counter = 0; // 重置计数，允许发送
        }
    }   

#if (USE_UART_DMA == 1)
    switch (port) {
        case USART1_PORT:
            {
                if(system_status.uart.uart1_dma_tx_busy)
                {
                    return;
                }
                system_status.uart.uart1_dma_tx_busy = 1;
                huart = &huart1;
            }
            break;
        case USART2_PORT:
            {
                if(system_status.uart.uart2_dma_tx_busy)
                {
                    return;
                }
                system_status.uart.uart2_dma_tx_busy = 1;
                huart = &huart2;
            }
            break;
        case USART3_PORT:
            {
                if(system_status.uart.uart3_dma_tx_busy)
                {
                    return;
                }
                system_status.uart.uart3_dma_tx_busy = 1;
                huart = &huart3;
            }
            break;
        default:
            return; // 无效的串口，直接返回
    }

    HAL_StatusTypeDef status = HAL_UART_Transmit_DMA(huart, send_data, size);

    if (status != HAL_OK) 
    {
        // 中止可能的DMA传输
        HAL_DMA_Abort(huart->hdmatx);
        // 重置UART和DMA的状态
        huart->gState = HAL_UART_STATE_READY;
        
        // 记录发送失败并更新错误计数
        switch (port)
        {
            case USART1_PORT:
                system_status.uart.uart1_error = status;
                system_status.uart.uart1_dma_tx_busy = 0;
                // 发送失败：增加错误计数和连续失败次数
                if (system_status.uart.uart1_error_count < 255) {
                    system_status.uart.uart1_error_count++;
                }
                if (system_status.uart.uart1_consecutive_send_failures < 255) {
                    system_status.uart.uart1_consecutive_send_failures++;
                }
                break;
            case USART2_PORT:
                system_status.uart.uart2_error = status;
                system_status.uart.uart2_dma_tx_busy = 0;
                // 发送失败：增加错误计数和连续失败次数
                if (system_status.uart.uart2_error_count < 255) {
                    system_status.uart.uart2_error_count++;
                }
                if (system_status.uart.uart2_consecutive_send_failures < 255) {
                    system_status.uart.uart2_consecutive_send_failures++;
                }
                break;
            case USART3_PORT:
                system_status.uart.uart3_error = status;
                system_status.uart.uart3_dma_tx_busy = 0;
                // 发送失败：增加错误计数和连续失败次数
                if (system_status.uart.uart3_error_count < 255) {
                    system_status.uart.uart3_error_count++;
                }
                if (system_status.uart.uart3_consecutive_send_failures < 255) {
                    system_status.uart.uart3_consecutive_send_failures++;
                }
                break;
        }
        
        // 检查是否需要设置全局错误标志
        if (system_status.uart.uart1_error_count > 3 || 
            system_status.uart.uart2_error_count > 3 || 
            system_status.uart.uart3_error_count > 3) {
            system_status.error |= SYS_ERROR_UART;
        }
    }
    else
    {
        switch (port)
        {
            case USART1_PORT:
                system_status.uart.uart1_error = 0;
                system_status.uart.uart1_error_code = 0;
                break;
            case USART2_PORT:
                system_status.uart.uart2_error = 0;
                system_status.uart.uart2_error_code = 0;
                break;
            case USART3_PORT:
                system_status.uart.uart3_error = 0;
                system_status.uart.uart3_error_code = 0;
                break;
        }
    }

#else
    switch (port) {
        case USART1_PORT:
            huart = &huart1;
            break;
        case USART2_PORT:
            huart = &huart2;
            break;
        case USART3_PORT:
            huart = &huart3;
            break;
        default:
            return; // 无效的串口，直接返回
    }
    // 发送数据
    if (HAL_UART_Transmit(huart, send_data, size, 100) != HAL_OK) 
    {
        // 处理发送错误
        system_status.usart.error = 1;
    } 
#endif
}

#include "app_config.h"
#include "app_midi.h"
#include "app_misc.h"
#include "app_msg.h"
#include "app_pwr.h"

/* 统一接收处理函数 */
static void drv_uart_process_reception(const uart_instance_t* instance, uint16_t size)
{
    system_status.is_communicating = 1;  // 添加通信标记
    __disable_irq();
    // 仅中止接收DMA通道，避免影响发送DMA
    // HAL_DMA_Abort(instance->hdma_rx);

    
    /* 关键修改点：直接调用 app_msg_enqueue 传递数据和端口号 */
    bool success = app_msg_enqueue(&uart_rx_queue,      
                                   instance->src_id,  
                                   instance->rx_buffer, 
                                   size);

    // 正常接收数据时，重置连续失败计数并直接清零错误计数
    if(success && size > 0) {
        if(instance->src_id == USART1_PORT) {
            system_status.uart.uart1_consecutive_send_failures = 0;
            system_status.uart.uart1_error_count = 0;
        } else if(instance->src_id == USART2_PORT) {
            system_status.uart.uart2_consecutive_send_failures = 0;
            system_status.uart.uart2_error_count = 0;
        } else if(instance->src_id == USART3_PORT) {
            system_status.uart.uart3_consecutive_send_failures = 0;
            system_status.uart.uart3_error_count = 0;
        }
    }

    /* 重置接收环境 */
    memset(instance->rx_buffer, 0, RX_BUF_SIZE);
    HAL_UARTEx_ReceiveToIdle_DMA(instance->huart, instance->rx_buffer, RX_BUF_SIZE);
    __HAL_DMA_DISABLE_IT(instance->hdma_rx, DMA_IT_HT);
    __enable_irq();
}


static void drv_uart_dma_restart(const uart_instance_t* instance)
{
    __disable_irq();
    HAL_DMA_Abort(instance->hdma_rx);
    memset(instance->rx_buffer, 0, RX_BUF_SIZE);
    HAL_UARTEx_ReceiveToIdle_DMA(instance->huart, instance->rx_buffer, RX_BUF_SIZE);
    __HAL_DMA_DISABLE_IT(instance->hdma_rx, DMA_IT_HT);
    __enable_irq();
}


/* 错误分类函数 */
static uart_error_level_t uart_error_classify(UART_HandleTypeDef *huart) 
{
    const uint32_t err = huart->ErrorCode;
    
    // 严重错误：关键错误组合（如奇偶校验+DMA错误）
    if ((err & (HAL_UART_ERROR_PE | HAL_UART_ERROR_NE | HAL_UART_ERROR_FE)) && 
        (err & (HAL_UART_ERROR_ORE | HAL_UART_ERROR_DMA))) {
        return UART_ERR_HARDWARE;
    }
    
    // DMA传输错误单独处理
    if (err & HAL_UART_ERROR_DMA) {
        return UART_ERR_DMA;
    }
    
    // 溢出错误处理优先级次之
    if (err & HAL_UART_ERROR_ORE) {
        return UART_ERR_OVERRUN;
    }
    
    // 常规可恢复错误
    if (err & (HAL_UART_ERROR_PE | HAL_UART_ERROR_FE | HAL_UART_ERROR_NE)) {
        return UART_ERR_RECOVERABLE;
    }
    
    return UART_ERR_RECOVERABLE; // 默认按可恢复处理
}

/* DMA错误处理 */
static void handle_dma_error(const uart_instance_t* instance) 
{
    __disable_irq();
    HAL_DMA_Abort(instance->hdma_rx);
    HAL_DMA_DeInit(instance->hdma_rx);
    HAL_DMA_Init(instance->hdma_rx); // 重新初始化DMA
    
    memset(instance->rx_buffer, 0, RX_BUF_SIZE);
    HAL_UARTEx_ReceiveToIdle_DMA(instance->huart, 
                                 instance->rx_buffer, 
                                 RX_BUF_SIZE);
    __HAL_DMA_DISABLE_IT(instance->hdma_rx, DMA_IT_HT);
    __enable_irq();
}

/* 溢出错误处理 */
static void handle_overrun_error(const uart_instance_t* instance) 
{
    __disable_irq();
    HAL_DMA_Abort(instance->hdma_rx);
    
    // 强制清空接收寄存器
    volatile uint32_t tmp;
    while(__HAL_UART_GET_FLAG(instance->huart, UART_FLAG_RXNE)) {
        tmp = instance->huart->Instance->DR;
        UNUSED(tmp);
    }
    
    // 重置DMA配置
    instance->hdma_rx->Instance->CMAR = (uint32_t)instance->rx_buffer;
    instance->hdma_rx->Instance->CNDTR = RX_BUF_SIZE;
    
    HAL_UARTEx_ReceiveToIdle_DMA(instance->huart, 
                                 instance->rx_buffer, 
                                 RX_BUF_SIZE);
    __HAL_DMA_DISABLE_IT(instance->hdma_rx, DMA_IT_HT);
    __enable_irq();
}

/* 硬件级复位 - 优化版，减少中断禁用时间 */
static void uart_hardware_reset(const uart_instance_t* instance) 
{
    // 保存配置（不需要禁用中断）
    UART_InitTypeDef uart_config = instance->huart->Init;
    
    // 短时间禁用中断进行关键操作
    __disable_irq();
    HAL_DMA_Abort(instance->hdma_rx);
    __enable_irq();
    
    // 复位外设（大部分操作不需要禁用中断）
    HAL_UART_DeInit(instance->huart);
    HAL_DMA_DeInit(instance->hdma_rx);
    
    // 重新初始化
    HAL_DMA_Init(instance->hdma_rx); 
    instance->huart->Init = uart_config;
    HAL_UART_Init(instance->huart);
    
    // 重启接收
    memset(instance->rx_buffer, 0, RX_BUF_SIZE);
    HAL_UARTEx_ReceiveToIdle_DMA(instance->huart, 
                                 instance->rx_buffer, 
                                 RX_BUF_SIZE);
    __HAL_DMA_DISABLE_IT(instance->hdma_rx, DMA_IT_HT);
}

/* 可恢复错误处理（优化版） */
static void handle_recoverable_error(const uart_instance_t* instance) 
{
    __disable_irq();
    HAL_DMA_Abort(instance->hdma_rx);
    
    // 彻底清除所有可能残留标志
    __HAL_UART_CLEAR_PEFLAG(instance->huart);
    __HAL_UART_CLEAR_FEFLAG(instance->huart);
    __HAL_UART_CLEAR_NEFLAG(instance->huart);
    __HAL_UART_CLEAR_OREFLAG(instance->huart);
    
    // 重启传输
    memset(instance->rx_buffer, 0, RX_BUF_SIZE);
    HAL_UARTEx_ReceiveToIdle_DMA(instance->huart, 
                                 instance->rx_buffer, 
                                 RX_BUF_SIZE);
    __HAL_DMA_DISABLE_IT(instance->hdma_rx, DMA_IT_HT);
    __enable_irq();
}

/* 统一错误处理函数 */
static void drv_uart_process_error(const uart_instance_t* instance)
{

    UART_HandleTypeDef *huart = instance->huart;
 
    // 错误分类
    const uart_error_level_t err_level = uart_error_classify(huart);
    

    // 分级处理
    switch(err_level) {
        case UART_ERR_RECOVERABLE:
            handle_recoverable_error(instance);
            break;
            
        case UART_ERR_OVERRUN:
            handle_overrun_error(instance);
            break;
            
        case UART_ERR_DMA:
            handle_dma_error(instance);
            break;
            
        case UART_ERR_HARDWARE:
            uart_hardware_reset(instance);
            break;
    }
    
    // 清除错误标记
    huart->ErrorCode = HAL_UART_ERROR_NONE;
    
    // 注意：错误计数不在这里清零，而是在正常通信恢复后逐步减少
}


void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t size)
{
    if(pwr_state == PWR_ON)
    {
        if(huart == &huart1)
        {
            drv_uart_process_reception(&uart1_instance, size);
        }
        else if (huart == &huart2)
        {
            drv_uart_process_reception(&uart2_instance, size);
        }
        else if(huart == &huart3)
        {
            drv_uart_process_reception(&uart3_instance, size);
        }
    }
    else
    {
        if(huart == &huart1)
        {
#if (APP_ENABLE_MIDI_AUTO_POWER_ON_UART1 == 1)
            app_midi_handle_cmd(uart1_rx_buffer, size);
#endif
            drv_uart_dma_restart(&uart1_instance);
        }
        else if (huart == &huart2)
        {
#if (APP_ENABLE_MIDI_AUTO_POWER_ON_UART2 == 1)
            app_midi_handle_cmd(uart2_rx_buffer, size);
#endif 
            drv_uart_dma_restart(&uart2_instance);
        }
        else if(huart == &huart3)
        {
#if (APP_ENABLE_MIDI_AUTO_POWER_ON_UART3 ==1)
            app_midi_handle_cmd(uart3_rx_buffer, size);
#endif
            drv_uart_dma_restart(&uart3_instance);
        }
    }
}


void HAL_UART_ErrorCallback(UART_HandleTypeDef * huart)
{
    system_status.dbg_flag = 1;
    
    // 局部化处理，避免影响其他串口
    if(huart == &huart1)
    {
        __disable_irq();
        system_status.uart.uart1_dma_tx_busy = 0;
        system_status.uart.uart1_error_code = huart->ErrorCode;
        __enable_irq();
        
        // 串口错误：增加错误计数
        if(system_status.uart.uart1_error_count < 255) {
            system_status.uart.uart1_error_count++;
        }
        
        // 检查是否需要设置全局错误标志
        if(system_status.uart.uart1_error_count > 3) {
            system_status.error |= SYS_ERROR_UART;
        }
        drv_uart_process_error(&uart1_instance);
    }
    else if (huart == &huart2)
    {
        __disable_irq();
        system_status.uart.uart2_dma_tx_busy = 0;
        system_status.uart.uart2_error_code = huart->ErrorCode;
        __enable_irq();
        
        // 串口错误：增加错误计数
        if(system_status.uart.uart2_error_count < 255) {
            system_status.uart.uart2_error_count++;
        }
        
        // 检查是否需要设置全局错误标志
        if(system_status.uart.uart2_error_count > 3) {
            system_status.error |= SYS_ERROR_UART;
        }
        drv_uart_process_error(&uart2_instance);
    }
    else if(huart == &huart3)
    {
        __disable_irq();
        system_status.uart.uart3_dma_tx_busy = 0;
        system_status.uart.uart3_error_code = huart->ErrorCode;  // 修复：使用正确的uart3字段
        __enable_irq();
        
        // 串口错误：增加错误计数
        if(system_status.uart.uart3_error_count < 255) {
            system_status.uart.uart3_error_count++;
        }
        
        // 检查是否需要设置全局错误标志
        if(system_status.uart.uart3_error_count > 3) {
            system_status.error |= SYS_ERROR_UART;
        }
        drv_uart_process_error(&uart3_instance);
    }
}

 
// UART 发送完成回调
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{ 
    /* 原子操作更新状态 */
    __disable_irq();
    if (huart == &huart1)
    {
        system_status.uart.uart1_dma_tx_busy = 0;
        // 发送成功：重置连续失败计数，直接清零错误计数
        system_status.uart.uart1_consecutive_send_failures = 0;
        system_status.uart.uart1_error_count = 0;
    }
    else if (huart == &huart2)
    {
        system_status.uart.uart2_dma_tx_busy = 0;
        // 发送成功：重置连续失败计数，直接清零错误计数
        system_status.uart.uart2_consecutive_send_failures = 0;
        system_status.uart.uart2_error_count = 0;
    }
    else if (huart == &huart3)
    {
        system_status.uart.uart3_dma_tx_busy = 0;
        // 发送成功：重置连续失败计数，直接清零错误计数
        system_status.uart.uart3_consecutive_send_failures = 0;
        system_status.uart.uart3_error_count = 0;
    }
    __enable_irq();
}


